/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.applicatioN.controllers;

import com.applicatioN.controllers.exceptions.IllegalOrphanException;
import com.applicatioN.controllers.exceptions.NonexistentEntityException;
import com.applicatioN.controllers.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import com.applicatioN.entities.Candidat;
import java.util.ArrayList;
import java.util.Collection;
import com.applicatioN.entities.Agent;
import com.applicatioN.entities.Bureau;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Asus_k53s
 */
public class BureauJpaController implements Serializable {

    public BureauJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Bureau bureau) throws PreexistingEntityException, Exception {
        if (bureau.getCandidatCollection() == null) {
            bureau.setCandidatCollection(new ArrayList<Candidat>());
        }
        if (bureau.getAgentCollection() == null) {
            bureau.setAgentCollection(new ArrayList<Agent>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Candidat> attachedCandidatCollection = new ArrayList<Candidat>();
            for (Candidat candidatCollectionCandidatToAttach : bureau.getCandidatCollection()) {
                candidatCollectionCandidatToAttach = em.getReference(candidatCollectionCandidatToAttach.getClass(), candidatCollectionCandidatToAttach.getIdentifiant());
                attachedCandidatCollection.add(candidatCollectionCandidatToAttach);
            }
            bureau.setCandidatCollection(attachedCandidatCollection);
            Collection<Agent> attachedAgentCollection = new ArrayList<Agent>();
            for (Agent agentCollectionAgentToAttach : bureau.getAgentCollection()) {
                agentCollectionAgentToAttach = em.getReference(agentCollectionAgentToAttach.getClass(), agentCollectionAgentToAttach.getNumeroDeMatricule());
                attachedAgentCollection.add(agentCollectionAgentToAttach);
            }
            bureau.setAgentCollection(attachedAgentCollection);
            em.persist(bureau);
            for (Candidat candidatCollectionCandidat : bureau.getCandidatCollection()) {
                Bureau oldNationaliteOfCandidatCollectionCandidat = candidatCollectionCandidat.getNationalite();
                candidatCollectionCandidat.setNationalite(bureau);
                candidatCollectionCandidat = em.merge(candidatCollectionCandidat);
                if (oldNationaliteOfCandidatCollectionCandidat != null) {
                    oldNationaliteOfCandidatCollectionCandidat.getCandidatCollection().remove(candidatCollectionCandidat);
                    oldNationaliteOfCandidatCollectionCandidat = em.merge(oldNationaliteOfCandidatCollectionCandidat);
                }
            }
            for (Agent agentCollectionAgent : bureau.getAgentCollection()) {
                Bureau oldPaysOfAgentCollectionAgent = agentCollectionAgent.getPays();
                agentCollectionAgent.setPays(bureau);
                agentCollectionAgent = em.merge(agentCollectionAgent);
                if (oldPaysOfAgentCollectionAgent != null) {
                    oldPaysOfAgentCollectionAgent.getAgentCollection().remove(agentCollectionAgent);
                    oldPaysOfAgentCollectionAgent = em.merge(oldPaysOfAgentCollectionAgent);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findBureau(bureau.getPays()) != null) {
                throw new PreexistingEntityException("Bureau " + bureau + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Bureau bureau) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Bureau persistentBureau = em.find(Bureau.class, bureau.getPays());
            Collection<Candidat> candidatCollectionOld = persistentBureau.getCandidatCollection();
            Collection<Candidat> candidatCollectionNew = bureau.getCandidatCollection();
            Collection<Agent> agentCollectionOld = persistentBureau.getAgentCollection();
            Collection<Agent> agentCollectionNew = bureau.getAgentCollection();
            List<String> illegalOrphanMessages = null;
            for (Agent agentCollectionOldAgent : agentCollectionOld) {
                if (!agentCollectionNew.contains(agentCollectionOldAgent)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Agent " + agentCollectionOldAgent + " since its pays field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Collection<Candidat> attachedCandidatCollectionNew = new ArrayList<Candidat>();
            for (Candidat candidatCollectionNewCandidatToAttach : candidatCollectionNew) {
                candidatCollectionNewCandidatToAttach = em.getReference(candidatCollectionNewCandidatToAttach.getClass(), candidatCollectionNewCandidatToAttach.getIdentifiant());
                attachedCandidatCollectionNew.add(candidatCollectionNewCandidatToAttach);
            }
            candidatCollectionNew = attachedCandidatCollectionNew;
            bureau.setCandidatCollection(candidatCollectionNew);
            Collection<Agent> attachedAgentCollectionNew = new ArrayList<Agent>();
            for (Agent agentCollectionNewAgentToAttach : agentCollectionNew) {
                agentCollectionNewAgentToAttach = em.getReference(agentCollectionNewAgentToAttach.getClass(), agentCollectionNewAgentToAttach.getNumeroDeMatricule());
                attachedAgentCollectionNew.add(agentCollectionNewAgentToAttach);
            }
            agentCollectionNew = attachedAgentCollectionNew;
            bureau.setAgentCollection(agentCollectionNew);
            bureau = em.merge(bureau);
            for (Candidat candidatCollectionOldCandidat : candidatCollectionOld) {
                if (!candidatCollectionNew.contains(candidatCollectionOldCandidat)) {
                    candidatCollectionOldCandidat.setNationalite(null);
                    candidatCollectionOldCandidat = em.merge(candidatCollectionOldCandidat);
                }
            }
            for (Candidat candidatCollectionNewCandidat : candidatCollectionNew) {
                if (!candidatCollectionOld.contains(candidatCollectionNewCandidat)) {
                    Bureau oldNationaliteOfCandidatCollectionNewCandidat = candidatCollectionNewCandidat.getNationalite();
                    candidatCollectionNewCandidat.setNationalite(bureau);
                    candidatCollectionNewCandidat = em.merge(candidatCollectionNewCandidat);
                    if (oldNationaliteOfCandidatCollectionNewCandidat != null && !oldNationaliteOfCandidatCollectionNewCandidat.equals(bureau)) {
                        oldNationaliteOfCandidatCollectionNewCandidat.getCandidatCollection().remove(candidatCollectionNewCandidat);
                        oldNationaliteOfCandidatCollectionNewCandidat = em.merge(oldNationaliteOfCandidatCollectionNewCandidat);
                    }
                }
            }
            for (Agent agentCollectionNewAgent : agentCollectionNew) {
                if (!agentCollectionOld.contains(agentCollectionNewAgent)) {
                    Bureau oldPaysOfAgentCollectionNewAgent = agentCollectionNewAgent.getPays();
                    agentCollectionNewAgent.setPays(bureau);
                    agentCollectionNewAgent = em.merge(agentCollectionNewAgent);
                    if (oldPaysOfAgentCollectionNewAgent != null && !oldPaysOfAgentCollectionNewAgent.equals(bureau)) {
                        oldPaysOfAgentCollectionNewAgent.getAgentCollection().remove(agentCollectionNewAgent);
                        oldPaysOfAgentCollectionNewAgent = em.merge(oldPaysOfAgentCollectionNewAgent);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = bureau.getPays();
                if (findBureau(id) == null) {
                    throw new NonexistentEntityException("The bureau with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Bureau bureau;
            try {
                bureau = em.getReference(Bureau.class, id);
                bureau.getPays();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The bureau with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Agent> agentCollectionOrphanCheck = bureau.getAgentCollection();
            for (Agent agentCollectionOrphanCheckAgent : agentCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Bureau (" + bureau + ") cannot be destroyed since the Agent " + agentCollectionOrphanCheckAgent + " in its agentCollection field has a non-nullable pays field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Collection<Candidat> candidatCollection = bureau.getCandidatCollection();
            for (Candidat candidatCollectionCandidat : candidatCollection) {
                candidatCollectionCandidat.setNationalite(null);
                candidatCollectionCandidat = em.merge(candidatCollectionCandidat);
            }
            em.remove(bureau);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Bureau> findBureauEntities() {
        return findBureauEntities(true, -1, -1);
    }

    public List<Bureau> findBureauEntities(int maxResults, int firstResult) {
        return findBureauEntities(false, maxResults, firstResult);
    }

    private List<Bureau> findBureauEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Bureau.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Bureau findBureau(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Bureau.class, id);
        } finally {
            em.close();
        }
    }

    public int getBureauCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Bureau> rt = cq.from(Bureau.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
